package com.toutiao.score

import scala.math.sqrt

import org.apache.log4j.Logger

class SimData(val sim_ct:Double,
		      val sim_te:Double,
		      val sim_gs:Array[String],
		      val sim_px:Int,
		      val sim_ns:Array[String],
		      val sim_ss:Array[String]
		       ) {
  
}

class SimScorer(
		s1: ScoreFeaturer,
		s2: MatchFeaturer,
		sim: Double = 0.6
    ) {
  
  private
  val _log = Logger.getLogger(this.getClass.getName)
  
  
  def cos(m1:Map[String,Double], s1:Double, m2:Map[String,Double], s2:Double):Double = {
    var s = 0.0
    for ( (k,v) <- m1){
      s += v*m2.getOrElse(k,0.0)
    }
    s/(s1*s2)
  }
  
  def cos(m1:Map[String,Double],m2:Map[String,Double]) = {
    
    val s1 = m1.values.map(v => v*v).sum
    val s2 = m2.values.map(v => v*v).sum
    
    var s = 0.0
    for ( (k,v) <- m1) {
      s += v*m2.getOrElse(k,0.0)
    }
    s/(sqrt(s1)*sqrt(s2))
 
  }
  
  def getSimScore(cutTitle1:String, cutContent1:String,
		  		  cutTitle2:String, cutContent2:String) = {
    
    val v1 = s1.getTFIDFScore(cutTitle1, cutContent1)
    val v2 = s1.getTFIDFScore(cutTitle2, cutContent2)
    
    val v1_content = s1.norm(v1, n=40)
    val v2_content = s1.norm(v2, n=40)
    val sim_content = cos(v1_content,1.0,v2_content,1.0)
    
    val title_vs1 = s1.cut(cutTitle1)
    val title_vs2 = s1.cut(cutTitle2)
    val v1_title = s1.getTitleScore(title_vs1,v1,30.0)
    val v2_title = s1.getTitleScore(title_vs2,v2,30.0)
    val sim_title = cos(v1_title,v2_title)
    
    val line1 = cutTitle1.replace(" ", "").trim.toLowerCase
    val line2 = cutTitle2.replace(" ", "").trim.toLowerCase
    
    val sim_gs = s2.getCommonSegment(line1, line2, nn=4).map(_._1)
    
    val xs = s2.getCommonSegment(line1,line2,nn=2)
    val sim_px = s2.getProximitySim(xs)
    
    val sim_ns = s2.getDigitSim(line1,line2)
    val sim_ss = s2.getSquareSim(line1,line2)
    
    
    new SimData(sim_content,sim_title,sim_gs,sim_px,sim_ns,sim_ss)
  }
  
  def getSimScore(cutTitle1:String, vm1:Map[String,Double],
		  		  cutTitle2:String, vm2:Map[String,Double]) = {
    val v1 = vm1
    val v2 = vm2
    
    val v1_content = s1.norm(v1, n=40)
    val v2_content = s1.norm(v2, n=40)
    val sim_content = cos(v1_content,1.0,v2_content,1.0)
    
    val title_vs1 = s1.cut(cutTitle1)
    val title_vs2 = s1.cut(cutTitle2)
    val v1_title = s1.getTitleScore(title_vs1,v1,30.0)
    val v2_title = s1.getTitleScore(title_vs2,v2,30.0)
    val sim_title = cos(v1_title,v2_title)
    
    val line1 = cutTitle1.replace(" ", "").trim.toLowerCase
    val line2 = cutTitle2.replace(" ", "").trim.toLowerCase
    
    val sim_gs = s2.getCommonSegment(line1, line2, nn=4).map(_._1)
    
    val xs = s2.getCommonSegment(line1,line2,nn=2)
    val sim_px = s2.getProximitySim(xs)
    
    val sim_ns = s2.getDigitSim(line1,line2)
    val sim_ss = s2.getSquareSim(line1,line2)
    
    
    new SimData(sim_content,sim_title,sim_gs,sim_px,sim_ns,sim_ss)    
  }
  
  def sum_ns(ns:Array[String]) = {
    ns.map(_.size).sum
  }
  def max_ns(ns:Array[String]) = {
    ns.map(_.size).max
  }
  
  def giveSimScore(cutTitle1:String, vm1:Map[String,Double],
		  		   cutTitle2:String, vm2:Map[String,Double]) = {
    val res = getSimScore(cutTitle1,vm1,cutTitle2,vm2)
    
    
    val sim1 = sim
    val sim2 = sim-0.1
    val sim3 = sim-0.2
    val sim4 = sim-0.3
    
    if (res.sim_ct > sim1) { // 内容相似度
      res.sim_ct
    }
    else if (res.sim_ct > sim3 && res.sim_te > sim1){ 
      _log.info("1 "+cutTitle1+" : "+cutTitle2)
      sim+0.01
    }
    else if (res.sim_ct > sim4 && res.sim_px >= 8){
      _log.info("2 "+cutTitle1+" : "+cutTitle2)
      sim+0.01
    }
    else if (res.sim_te > sim1 && res.sim_px >= 8){
      _log.info("3 "+cutTitle1+" : "+cutTitle2)
      sim+0.01
    }
    else if (res.sim_te > sim3 && res.sim_px >= 10){
      _log.info("4 "+cutTitle1+" : "+cutTitle2)
      sim+0.01
    }
    else if (res.sim_te > sim3 && res.sim_ct > sim2 && res.sim_px >= 5){
      _log.info("5 "+cutTitle1+" : "+cutTitle2)
      sim+0.01
    }
    else if (res.sim_ct > sim4 && res.sim_ct > sim3 && res.sim_gs.size > 0 && sum_ns(res.sim_gs) >= 8){
      _log.info("6 "+cutTitle1+" : "+cutTitle2)
      sim+0.01
    }
    else if (res.sim_ct > sim3 && res.sim_te > sim4 && res.sim_ns.size > 0){
      _log.info("7 "+cutTitle1+" : "+cutTitle2)
      sim+0.01
    }
    else if (res.sim_ct + res.sim_te > sim3 && res.sim_px >= 8 && (res.sim_ns.size > 0 || res.sim_ss.size > 0)){
      _log.info("8 "+cutTitle1+" : "+cutTitle2)
      sim+0.01
    }
    else if (res.sim_ct + res.sim_te > sim3 && res.sim_gs.size > 0 && sum_ns(res.sim_gs) >= 6 && (res.sim_ns.size > 0 || res.sim_ss.size > 0)){
      _log.info("9 "+cutTitle1+" : "+cutTitle2)
      sim+0.01
    }
    else if (res.sim_gs.size == 0 && res.sim_px >= 5 && res.sim_ct > sim2 && res.sim_te > sim2){
      _log.info("0 "+cutTitle1+" : "+cutTitle2)
      sim+0.01
    }
    else {
      res.sim_ct
    }
  }

}